<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch } from 'vue'
import AMapLoader from '@amap/amap-jsapi-loader'

interface MarkerItem {
  position: [number, number]
  title: string
  [key: string]: any
}

interface Props {
  option: Record<string, any>
  markersData: MarkerItem[]
}

const props = withDefaults(defineProps<Props>(), {
  option: () => ({}),
  markersData: () => []
})

let AMap = null
let map = null
let layer = null
const containerRef = ref()

const initMap = async () => {
  ;(window as any)._AMapSecurityConfig = {
    securityJsCode: '28e8061333fac3079ee854fef632196e'
  }
  await AMapLoader.load({
    key: '63cb2b48301b336ee761198b2b661410',
    version: '2.0',
    plugins: ['AMap.Scale']
  })
    .then((res) => {
      AMap = res

      map = new AMap.Map(containerRef.value, {
        viewMode: '3D', // 是否为3D地图模式
        ...props.option
      })

      layer = new AMap.LabelsLayer({
        zooms: [3, 20],
        zIndex: 1000,
        collision: false
      })

      map.add(layer)
    })
    .catch((e) => {
      console.log(e)
    })
}

let markers = []
let normalMarker
let icon = {
  type: 'image',
  image: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
  size: [19, 31],
  anchor: 'bottom-center'
}

const initMarkersData = () => {
  if (!layer) return

  layer.remove(markers)
  markers = []

  if (!normalMarker) normalMarker = new AMap.Marker({ anchor: 'bottom-center', offset: [0, -40] })

  const markersData: any = JSON.parse(JSON.stringify(props.markersData))

  markersData.forEach((item) => {
    const labelMarker = new AMap.LabelMarker({
      extData: item.extData,
      position: item.position,
      icon
    })

    labelMarker.on('mouseover', function (e) {
      let { position } = e.data.data

      if (position) {
        const extData = e.target.getExtData()

        normalMarker.setContent(
          '<div class="amap-info-window">' +
            extData.content +
            '<div class="amap-info-sharp"></div>' +
            '</div>'
        )
        normalMarker.setPosition(position)
        map.add(normalMarker)
      }
    })

    labelMarker.on('mouseout', function () {
      map.remove(normalMarker)
    })

    markers.push(labelMarker)
  })

  layer.add(markers)
}

watch(
  [() => props.option],
  () => {
    initMap().then((res) => {
      initMarkersData()
    })
  },
  { deep: true }
)

// watchEffect由于if (!AMap) return追踪initMarkersData失败

watch(
  [() => props.markersData],
  () => {
    initMarkersData()
  },
  { deep: true }
)

onMounted(() => {
  initMap().then((res) => {
    initMarkersData()
  })
})

onUnmounted(() => {
  map?.destroy()
})
</script>

<template>
  <div ref="containerRef" class="map-container"></div>
</template>

<style scoped>
.map-container {
  width: 100%;
  height: 100%;
}

.map-container :deep(.amap-logo),
.map-container :deep(.amap-copyright) {
  display: none !important;
}

:deep(.amap-info-window) {
  width: 150px;
  color: #999;
  background: #fff;
  border-radius: 3px;
  padding: 3px 7px;
  box-shadow: 0 2px 6px 0 rgba(114, 124, 245, 0.5);
  position: relative;
}
:deep(.amap-info-sharp) {
  position: absolute;
  bottom: 0;
  left: 50%;
  margin-left: -8px;
  margin-bottom: -8px;
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-top: 8px solid #fff;
}
</style>
